package com.thebox.config;

import java.util.*;

import org.apache.commons.beanutils.*;
import org.apache.log4j.Logger;

import linuxbox.common.*;
import linuxbox.exception.LinuxboxException;
import linuxbox.BoxStatic;

public class ModuleConfig {
    protected static Logger logger = Logger.getLogger
        (ModuleConfig.class.getName());

    private String name = null;
    private String version = null;
    private String required = null;
    private String category = null;
    private String fullName = null;
    private String icon = null;
    private String url = null;
    private String urlType = null;
    private String newUrl = null;

    private List initParamList = null;
    private Map initParamMap = null;
    //private Map actionMap;
    private List actionList = null;

    //Keeps the modules that can be displayed in home page
    List homepageModuleList = new ArrayList();
    //Map homepageModules = new HashMap();

    //Keeps the modules that can be displayed in Admin page
    List adminModuleList = new ArrayList();
    //Map adminModules = new HashMap();

    Map init_settings = new HashMap(); //Keeps the init parameters
    Map settings = new HashMap(); //Keeps the module settings

    public ModuleConfig() {
        initParamList = new ArrayList();
        initParamMap = new HashMap();
        //actionMap = new HashMap();
        actionList = new ArrayList();
    }

    public void setName(String str) {
        name = str;
    }

    public String getName() {
        return name;
    }

    public void setVersion(String str) {
        version = str;
    }

    public String getVersion() {
        return version;
    }

    public void setRequired(String str) {
        required = str;
    }

    public String getRequired() {
        return required;
    }

    public void setCategory(String str) {
        category = str;
    }

    public String getCategory() {
        return category;
    }

    public void setFullName(String str) {
        fullName = str;
    }

    public String getFullName() {
        return fullName;
    }

    public void setIcon(String str) {
        icon = str;
    }

    public String getIcon() {
        return icon;
    }

    public void setUrl(String u, String ut) {
        url = u;
        urlType = ut;
    }

    public String getURL() {
        if (newUrl == null) {
            if (urlType != null) {
                if (urlType.compareTo("jsp") == 0) {
                    newUrl = BoxStatic.jspDir + url;
                } else if (urlType.compareTo("servlet") == 0) {
                    newUrl = BoxStatic.servletDir + url;
                }
            }
        }

        return newUrl;
    }

    public void addInitParam(Param p) {
        //debug(p);
        initParamList.add(p);
    }

    public void addAction(Action a) {
        actionList.add(a);
    }

    public void addAdminModule(AdminModule am) {
        adminModuleList.add(am);
    }

    public void addHomepageModule(HomepageModule hm) {
        homepageModuleList.add(hm);
    }

    public List getHomepageModuleList() {
    	return homepageModuleList;
    }

    public List getAdminModuleList() {
    	return adminModuleList;
    }

    public linuxbox.common.Action getAction(String name) throws LinuxboxException {
        linuxbox.common.Action actionObj = null;
        for (Iterator it = actionList.iterator(); it.hasNext(); ) {
            com.thebox.config.Action ac = (com.thebox.config.Action)it.next();
            String name2 = ac.getName();
            if (name.equals(name2)) {
                String classPath = ac.getClassPath();

                try {
                    logger.debug("Attempting to load class " + classPath);

                    Class c = Class.forName(classPath);
                    actionObj = (linuxbox.common.Action)c.newInstance();
                } catch (ClassNotFoundException exc) {
                    throw new LinuxboxException(exc.getMessage());
                } catch (InstantiationException ie) {
                    throw new LinuxboxException(ie.getMessage());
                } catch (IllegalAccessException iae) {
                    throw new LinuxboxException(iae.getMessage());
                }

                List paramList = ac.getParamList();
                setBeanProperties(actionObj, paramList);
            }
        }
        return actionObj;
    }

    private void setBeanProperties(linuxbox.common.Action actionObj, List aList)
        throws LinuxboxException {
        try {
            for (Iterator it = aList.iterator(); it.hasNext(); ) {
                ActionParam ap = (ActionParam)it.next();
                String desc = ap.getDesc();
                String value = ap.getValue();
                BeanUtils.setProperty(actionObj, desc, value);
            }
        } catch (Exception exc) {
            throw new LinuxboxException(exc.getMessage());
        }
    }

    public void init() {
        for (Iterator it = initParamList.iterator(); it.hasNext(); ) {
            Param pa = (Param)it.next();
            Map map = getConfigTable(pa.getCategory(), init_settings);
            map.put(pa.getName(), pa.getValue());

            // my own map
            initParamMap.put(pa.getName(), pa);
        }
    }

    public void zFinish() {
        debug("------- z finish ----------");
        String newline = System.getProperty("line.separator");
        StringBuffer buf = new StringBuffer();

        buf.append("Module Config - ").append(name).append(newline);
        buf.append("version=").append(version).append(" requried=")
            .append(required).append(newline);

        debug(buf.toString());
        debug("------- z finish ----------\n");
    }

    public String getInitConfigValue(String category, String name) {
        Map map = getConfigTable(category, init_settings);
        return (String)map.get(name);
    }

    public String[] getInitConfigValues(String category, String name) {
        Map map = getConfigTable(category, init_settings);
        return (String[])map.get(name);
    }

    public String getConfigValue(String category, String name) {
        // First get from settings table
        Map map = getConfigTable(category, settings);
        String val = (String)map.get(name);
        if (val != null)
            return val;

        // if the cache doesn't have it yet, get from the database
        try {
            if (logger.isDebugEnabled()) {
                logger.debug("Try to get from module config: " + this.name
                             + " : " + category + " : " + name);
            }
            val = (String)BoxConfigUtil.getModuleConfigValue(this.name,
                                                         category, name);
        } catch (Exception e) {
            val = null;
        }

        if (val == null) {
            // not in databse then we will use the init value
            if (logger.isDebugEnabled()) {
                logger.debug("Try to get from module init parameter: "
                             + this.name + ":" + category + ":" + name);
            }
            val = getInitConfigValue(category, name);
        }

        if (val == null) {
            logger.error("Please set the init parameter for : "
                         + this.name + ":" + category + ":" + name);
        }
        map.put(name, val);
        return val;
    }

    public String[] getConfigValues(String category, String name) {
        // First get from settings table
        Map map = getConfigTable(category, settings);
        String[] val = (String[])map.get(name);
        if (val != null)
            return val;

        // if the cache doesn't have it yet, get from the database
        try {
            val = (String[])BoxConfigUtil.getModuleConfigValues
                (this.name, category, name);
        } catch (Exception e) {
            val = null;
        }

        if (val == null) {
            // not in databse then we will use the init value
            val = getInitConfigValues(category, name);
            if (val == null) {
                logger.error("Please set the init parameter for : "
                             + this.name + ":" + category + ":" + name);
            }
        }
        map.put(name, val);
        return val; // null is possible for String[] settings.
    }

    public boolean setConfigValue(String category, String name, String value) {
        try {
            Map map = getConfigTable(category, settings);
            BoxConfigUtil.setModuleConfigValue(this.name, category, name, value);
            map.remove(name);
            map.put(name, value);
        } catch (Exception e) {
            if (logger.isDebugEnabled())
                logger.debug("Error set config:" + this.name + category + name);
            return false;
        }
        return true;
    }

    public boolean setConfigValues(String category, String name, String[] value) {
        try {
            Map map = getConfigTable(category, settings);
            BoxConfigUtil.setModuleConfigValues(this.name, category, name, value);
            map.remove(name);
            map.put(name, value);
        } catch (Exception e) {
            if (logger.isDebugEnabled())
                logger.debug("Error set config:" + this.name + category + name);
            return false;
        }
        return true;
    }

    protected Map getConfigTable(String category, Map map) {
        Map val = (Map) map.get(category);
        if (val == null) {
            val = new HashMap();
            map.put(category, val);
        }
        return val;
    }

    public String toString() {
        String newline = System.getProperty("line.separator");
        StringBuffer buf = new StringBuffer();

        buf.append("Module Config - ").append(name).append(newline);
        buf.append("version=").append(version).append(" requried=")
            .append(required).append(newline);
        buf.append("category=").append(category).append(" fullName=")
            .append(fullName).append(newline);
        buf.append(" icon=").append(icon).append(" url=")
            .append(url + "[" + urlType + "]").append(newline);

        if (initParamMap.size() > 0) {
            buf.append(newline).append( "--- init param ---" ).append(newline);
            for (Iterator it = initParamMap.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry en = (Map.Entry)it.next();
                buf.append("key=").append((String)en.getKey());
                buf.append(" value=").append((Param)en.getValue()).append(newline);
            }
        }

        if (actionList.size() > 0) {
            buf.append(newline).append( "--- action list ---" ).append(newline);
            for (Iterator it = actionList.iterator(); it.hasNext(); ) {
                buf.append(it.next()).append(newline);
            }
        }

        if (adminModuleList.size() > 0) {
            buf.append(newline).append( "--- AdminModules ---" ).append(newline);
            for (Iterator it = adminModuleList.iterator(); it.hasNext(); ) {
                buf.append(it.next()).append(newline);
            }
        }

        if (homepageModuleList.size() > 0) {
            buf.append(newline).append( "--- HomepageModules ---" ).append(newline);
            for (Iterator it = homepageModuleList.iterator(); it.hasNext(); ) {
                buf.append(it.next()).append(newline);
            }
        }

        return buf.toString();
    }

    public static void debug(Object obj) {
        System.out.println("From ModuleConfig.java: " + obj);
    }
}
